__DefGroup HALU : [ALL]
  __Encoding
    field<12,  3> Pred pg = PT;
    field<15,  1> PModi pg.not = False;

__DefGroup H_ARITH : [HALU]
  __Encoding
    field<16,  8> Reg rd;
    field<24,  8> Reg ra;

    field<72,  1> SignModi ra.neg = False;
    field<73,  1> SignModi ra.abs = False;
    field<80,  2> HSel2 ra.hsel2 = H1_H0;

    field<76,  1> FPFtz ftz = NoFTZ;
    field<77,  1> FPSat sat = NoSAT;
    // field<78,  2> FPRound rnd == RN;

    field<94,  1> HFmtV2 hfmt_v2 = F16_V2;

  __Exception
    EncodingError<IllegalBitFieldCombination, "BF16_V2 doesnot support .FTZ/.SAT."> = (hfmt_v2=="BF16_V2") and (ftz=="FTZ" or sat=="SAT");

//HADD2 Begin
__DefOptype HADD2 : [H_ARITH]
  __Encoding
    field< 0,  8> Optype optype == HADD2;

  __Syntax
```asm          
HADD2{.hfmt_v2}{.FTZ}{.SAT}{.rnd}{.F32} Rd, {-}{|}Ra{.hsel2}{|}, {-}{|}SrcB{.hsel2}{|}      $sched $req ;

.hfmt_v2 = {.F16_V2*, .BF16_V2}
.rnd = {.RN*, .RP, .RM, .RZ}
.hsel2 = {.H1_H0*, .H0_H0, .H1_H1}
```

  __Description
执行双路输入16bit浮点数的加法，即Rd = Ra + SrcB。

输入输出均为32bit，表示两路加法所涉及的操作数。
其中第1路求和结果写入Rd的低16bit，第2路求和结果写入Rd的高16bit。

  __OperandInfo
Ra和Rd必须来源于GPR。

SrcB的来源可以是GPR、UR、F16ImmX2或cmem。

F16ImmX2类型浮点向量立即数的使用规范请参考[浮点数向量立即数](操作数汇编显示规则.md#浮点数向量立即数)。

对于非立即数的输入，可以选择添加负号、绝对值和.hsel2修饰符。
.hsel2修饰符的含义见下面__ModifierInfo的说明。

同时存在多种修饰符时，按照：先取绝对值，再取相反数的优先级次序结合。

  __ModifierInfo
.hfmt_v2表示输入/输出操作数的类型，可取值包括.F16_V2（默认值，可省略）和.BF16_V2。

.rnd可取.RN（默认值，可省略）、.RP、.RM和.RZ，表示计算结果的舍入模式：

| .rnd  | 舍入模式 |
|:--:|:---|
|.RN | 尾数四舍五入 |
|.RP | 尾数向正无穷方向舍入 |
|.RM | 尾数向负无穷方向舍入 |
|.RZ | 尾数向零（原点）舍入 |

操作数修饰符.hsel2可取值为.H1_H0（默认，可省略）、.H0_H0或.H1_H1。

| .hsel2 | 含义 |
|:--:|:---|
|.H1_H0| 选取32bit输入的低16bit作为第1路输入，高16bit作为第2路输入|
|.H0_H0| 选取32bit输入的低16bit复制2份，同时作为2路的输入 |
|.H1_H1| 选取32bit输入的高16bit复制2份，同时作为2路的输入 |

如果输入为F16ImmX2立即数，则直接以立即数的低16bit和高16bit分别作为第1路和第2路输入。

可选修饰符.FTZ表示如果输入/输出中有非规格化浮点数（subnormal number），则将其转换为有符号0（即保持符号位不变，其他bit全部置0）。

可选修饰符.SAT表示将结果截断到[+0.0, 1.0]的范围。

可选修饰符.F32表示舍弃第2路结果，仅将第1路求和结果转换为F32浮点数，写入Rd。

  __Semantics
16bit浮点数加法的语义基本与32bit浮点数一致，请参考
[[FADD]]指令的Semantics部分。

HADD2指令的求和结果可能产生NAN，对NAN的处理规则参考[浮点数NAN处理规则](浮点数NAN处理规则.md)。

  __Examples
```asm
HADD2        R0, R1.H0_H0,    R2 ; // {R0.H1,R0.H0} = {R1.H0,R1.H0} + {R2.H1,R2.H0}
HADD2.SAT    R3,       R6,   -R7 ; // {R3.H1,R3.H0} = {R6.H1,R6.H0} - {R7.H1,R7.H0}
HADD2.RN.FTZ R1,    -|R4|, -1, 1 ; // {R1.H1,R1.H0} = -|{R4.H1,R4.H0}| + {-1, 1}
```

  __Simulation
      vd = HADD2(va, vb);

__DefOpcode HADD2_RR : [HADD2]
  __Encoding
    field< 8,  4> SType stype == RR;
    field<32,  8> Reg rb;
    field<96,  1> SignModi rb.neg = False;
    field<97,  1> SignModi rb.abs = False;
    field<82,  2> HSel2 rb.hsel2 = H1_H0;
  __OperandInfo
    InList<pg, ra, rb>;
    OutList<rd>;
    Order<pg, rd, ra, rb>;
    Bitwidth<rd> = 32;
    Bitwidth<ra> = 32;
    Bitwidth<rb> = 32;

  __Exception

__DefOpcode HADD2_RU : [HADD2]
  __Encoding
    field< 8,  4> SType stype == RU;

    field<32,  6> UReg urb;

    field<96,  1> SignModi urb.neg = False;
    field<97,  1> SignModi urb.abs = False;
    field<82,  2> HSel2 urb.hsel2 = H1_H0;
  __OperandInfo
    InList<pg, ra, urb>;
    OutList<rd>;
    Order<pg, rd, ra, urb>;
    Bitwidth<rd> = 32;
    Bitwidth<ra> = 32;
    Bitwidth<urb> = 32;

__DefOpcode HADD2_RI : [HADD2]
  __Encoding
    field< 8,  4> SType stype == RI;
    field<32, 32> F16ImmX2 vb;

  __OperandInfo
    InList<pg, ra, vb>;
    OutList<rd>;
    Order<pg, rd, ra, vb>;
    Bitwidth<rd> = 32;
    Bitwidth<ra> = 32;
    Bitwidth<vb> = 32;
    AsmFormat<vb> = CvtFImm(vb, hfmt_v2);

__DefOpcode HADD2_RC : [HADD2]
  __Encoding
    field< 8,  4> SType stype == RC;
    field<32, 22> CMem vb;
    field<96,  1> SignModi vb.neg = False;
    field<97,  1> SignModi vb.abs = False;
    field<82,  2> HSel2 vb.hsel2 = H1_H0;
  __OperandInfo
    InList<pg, ra, vb>;
    OutList<rd>;
    Order<pg, rd, ra, vb>;
    Bitwidth<rd> = 32;
    Bitwidth<ra> = 32;
    Bitwidth<vb> = 32;

__DefOptype HMUL2 : [H_ARITH]
  __Encoding
    field< 0,  8> Optype optype == HMUL2;

  __Syntax
```asm          
HMUL2{.hfmt_v2}{.FTZ}{.SAT}{.rnd} Rd, {-}{|}Ra{.hsel2}{|}, {-}{|}SrcB{.hsel2}{|}      $sched $req ;

.hfmt_v2 = {.F16_V2*, .BF16_V2}
.rnd = {.RN*, .RP, .RM, .RZ}
.hsel2 = {.H1_H0*, .H0_H0, .H1_H1}
```

  __Description
执行双路输入16bit浮点数的乘法，即Rd = Ra * SrcB。

输入输出均为32bit，表示两路乘法所涉及的操作数。
其中第1路乘法结果写入Rd的低16bit，第2路乘法结果写入Rd的高16bit。

  __OperandInfo
Ra和Rd必须来源于GPR。

SrcB的来源可以是GPR、UR、cmem或F16ImmX2。

F16ImmX2类型浮点向量立即数的使用规范请参考[浮点数向量立即数](操作数汇编显示规则.md#浮点数向量立即数)。

对于非立即数的输入，可以选择添加负号、绝对值和.hsel2修饰符。
.hsel2修饰符的含义见下面__ModifierInfo的说明。

同时存在多种修饰符时，按照：先取绝对值，再取相反数的优先级次序结合。

  __ModifierInfo
.hfmt_v2表示输入/输出操作数的类型，可取值包括.F16_V2（默认值，可省略）和.BF16_V2。

.rnd可取.RN（默认值，可省略）、.RP、.RM和.RZ，表示计算结果的舍入模式：

| .rnd  | 舍入模式 |
|:--:|:---|
|.RN | 尾数四舍五入 |
|.RP | 尾数向正无穷方向舍入 |
|.RM | 尾数向负无穷方向舍入 |
|.RZ | 尾数向零（原点）舍入 |

操作数修饰符.hsel2可取值为.H1_H0（默认，可省略）、.H0_H0或.H1_H1。

| .hsel2 | 含义 |
|:--:|:---|
|.H1_H0| 选取32bit输入的低16bit作为第1路输入，高16bit作为第2路输入|
|.H0_H0| 选取32bit输入的低16bit复制2份，同时作为2路的输入 |
|.H1_H1| 选取32bit输入的高16bit复制2份，同时作为2路的输入 |

如果输入为F16ImmX2立即数，则直接以立即数的低16bit和高16bit分别作为第1路和第2路输入。

可选修饰符.FTZ表示如果输入/输出中有非规格化浮点数（subnormal number），则将其转换为有符号0（即保持符号位不变，其他bit全部置0）。

可选修饰符.SAT表示将结果截断到[+0.0, 1.0]的范围。

  __Semantics
16bit浮点数乘法的语义基本与32bit浮点数一致，请参考
[[FMUL]]指令的Semantics部分。

HMUL2指令的乘法结果可能产生NAN，对NAN的处理规则参考[浮点数NAN处理规则](浮点数NAN处理规则.md)。

  __Examples
```asm
HMUL2        R0,    R1,        R2 ; // {R0.H1,R0.H0} = {R1.H1,R1.H0} * {R2.H1,R2.H0}
HMUL2.SAT    R3,    R6, -R7.H0_H0 ; // {R3.H1,R3.H0} = {R6.H1,R6.H0} * (-{R7.H0,R7.H0})
HMUL2.RN.FTZ R1, -|R4|,     0, -1 ; // {R1.H1,R1.H0} = -|{R4.H1,R4.H0}| * {+0.0,-1.0}
```

  __Simulation
      vd = HMUL2(va, vb);

__DefOpcode HMUL2_RR : [HMUL2]
  __Encoding
    field< 8,  4> SType stype == RR;
    field<32,  8> Reg rb;
    field<96,  1> SignModi rb.neg = False;
    field<97,  1> SignModi rb.abs = False;
    field<82,  2> HSel2 rb.hsel2 = H1_H0;
  __OperandInfo
    InList<pg, ra, rb>;
    OutList<rd>;
    Order<pg, rd, ra, rb>;
    Bitwidth<rd> = 32;
    Bitwidth<ra> = 32;
    Bitwidth<rb> = 32;

  __Exception

__DefOpcode HMUL2_RU : [HMUL2]
  __Encoding
    field< 8,  4> SType stype == RU;
    field<32,  6> UReg urb;
    field<96,  1> SignModi urb.neg = False;
    field<97,  1> SignModi urb.abs = False;
    field<82,  2> HSel2 urb.hsel2 = H1_H0;
  __OperandInfo
    InList<pg, ra, urb>;
    OutList<rd>;
    Order<pg, rd, ra, urb>;
    Bitwidth<rd> = 32;
    Bitwidth<ra> = 32;
    Bitwidth<urb> = 32;

__DefOpcode HMUL2_RI : [HMUL2]
  __Encoding
    field< 8,  4> SType stype == RI;
    field<32, 32> F16ImmX2 vb;
  __OperandInfo
    InList<pg, ra, vb>;
    OutList<rd>;
    Order<pg, rd, ra, vb>;
    Bitwidth<rd> = 32;
    Bitwidth<ra> = 32;
    Bitwidth<vb> = 32;
    AsmFormat<vb> = CvtFImm(vb, hfmt_v2);

__DefOpcode HMUL2_RC : [HMUL2]
  __Encoding
    field< 8,  4> SType stype == RC;
    field<32, 22> CMem vb;
    field<96,  1> SignModi vb.neg = False;
    field<97,  1> SignModi vb.abs = False;
    field<82,  2> HSel2 vb.hsel2 = H1_H0;
  __OperandInfo
    InList<pg, ra, vb>;
    OutList<rd>;
    Order<pg, rd, ra, vb>;
    Bitwidth<rd> = 32;
    Bitwidth<ra> = 32;
    Bitwidth<vb> = 32;

__DefOptype HFMA2 : [H_ARITH]
  __Encoding
    field< 0,  8> Optype optype == HFMA2;
    field<92,  1> RELU relu = NoRELU;

  __Syntax
```asm          
HFMA2{.hfmt_v2}{.FTZ}{.RELU}{.SAT}{.rnd} Rd, {-}{|}Ra{.hsel2}{|}, {-}{|}SrcB{.hsel2}{|}, {-}{|}SrcC{.hsel2}{|}      $sched $req ;

.hfmt_v2 = {.F16_V2*, .BF16_V2}
.rnd = {.RN*, .RP, .RM, .RZ}
.hsel2 = {.H1_H0*, .H0_H0, .H1_H1}
```

  __Description
执行2路16bit输入浮点数的融合乘加运算，即Rd = Ra * SrcB + SrcC。

输入输出均为32bit，表示两路乘加所涉及的操作数。
其中第1路结果写入Rd的低16bit，第2路结果写入Rd的高16bit。

注意：Ra * SrcB的乘法是以全精度计算的，可以认为完全精确，乘积再与SrcC相加，最后再舍入到浮点数。

  __OperandInfo
Ra和Rd必须是来源于GPR的操作数。

SrcB和SrcC的合法来源组合包括：

| SrcB | SrcC |
|:--:|:--:|
| GPR | GPR |
| GPR | UR  |
| UR  | GPR |
| GPR |cmem |
|cmem | GPR |
|F16ImmX2 | GPR |
| GPR | F16ImmX2 |

F16ImmX2类型浮点向量立即数的使用规范请参考[浮点数向量立即数](操作数汇编显示规则.md#浮点数向量立即数)。

对于非立即数的输入，可以选择添加负号、绝对值和.hsel2修饰符。
.hsel2修饰符的含义见下面__ModifierInfo的说明。

同时存在多种修饰符时，按照：先取绝对值，再取相反数的优先级次序结合。

  __ModifierInfo
.hfmt_v2表示输入/输出操作数的类型，可取值包括.F16_V2（默认值，可省略）和.BF16_V2。

.rnd可取.RN（默认值，可省略）、.RP、.RM和.RZ，表示计算结果的舍入模式：

| .rnd  | 舍入模式 |
|:--:|:---|
|.RN | 尾数四舍五入 |
|.RP | 尾数向正无穷方向舍入 |
|.RM | 尾数向负无穷方向舍入 |
|.RZ | 尾数向零（原点）舍入 |

操作数修饰符.hsel2可取值为.H1_H0（默认，可省略）、.H0_H0或.H1_H1。

| .hsel2 | 含义 |
|:--:|:---|
|.H1_H0| 选取32bit输入的低16bit作为第1路输入，高16bit作为第2路输入|
|.H0_H0| 选取32bit输入的低16bit复制2份，同时作为2路的输入 |
|.H1_H1| 选取32bit输入的高16bit复制2份，同时作为2路的输入 |

如果输入为F16ImmX2立即数，则直接以立即数的低16bit和高16bit分别作为第1路和第2路输入。

可选修饰符.FTZ表示如果输入/输出中有非规格化浮点数（subnormal number），则将其转换为有符号0（即保持符号位不变，其他bit全部置0）。

可选修饰符.SAT表示将结果截断到[+0.0, 1.0]的范围。

可选修饰符.RELU表示将计算结果中的负数（包括-Inf）截断到+0.0。

.SAT修饰符和.RELU修饰符是互斥的，不可共存。

  __Semantics
```asm
HFMA2.hfmt_v2.ftz.relu.sat.rnd Rd, Ra.hsel2, SrcB.hsel2, SrcC.hsel2:
    // .SAT与.RELU互斥
    assert(.relu != .RELU || .sat != .SAT, ".RELU and .SAT are mutually exclusive");
    
    // 分2路计算，2路是同时进行的
    for (i = 0; i < 2; i++) {
        // 根据.hsel2，选取第i路的输入
        a = chooseInput(Ra  , i, Ra.hsel2);
        b = chooseInput(SrcB, i, SrcB.hsel2);
        c = chooseInput(SrcC, i, SrcC.hsel2);
        // 处理输入中的非规格化浮点数
        if (.ftz == .FTZ) {
            if (isSubnormal(a) == true) {
                a = signZero(a);
            }
            if (isSubnormal(b) == true) {
                b = signZero(b);
            }
            if (isSubnormal(c) == true) {
                c = signZero(c);
            }
        }
        // 计算乘法（无舍入）
        t = a * b;
        // 计算加法，然后根据.rnd舍入到.hfmt_v2类型的浮点数
        d = round(t + c, .rnd, .hfmt_v2);
        // 对结果进行clamp，
        if (.sat == .SAT) {
            // 对NAN做特殊处理
            if (isNAN(d) == true) {
                d = +0.0;
            } else {
                // 将结果饱和到[+0.0, 1.0]
                d = clamp(d, +0.0, 1.0);
            }
        } else if (.relu == .RELU) {
            // 将负数（包括-Inf）转换为+0.0
            d = d < +0.0 ? +0.0 : d;
        }
        // 对结果中的非规格化数进行处理
        if (.ftz == .FTZ) {
            if (isSubnormal(d) == true) {
                d = signZero(d);
            }
        }
        // 结果中的NAN统一转换为QNAN
        if (isNAN(d) == true) {
            d[15:0] = 0x7FFF;
        }
        // 输出到Rd寄存器
        if (i == 0) {
            Rd[15:0] = d & 0xFFFF;
        } else {
            Rd[31:16] = d & 0xFFFF;
        }
    }
```

浮点乘法和加法中的特殊值，在遵守
[IEEE 754浮点加法乘法特殊规则](IEEE754浮点加法乘法特殊规则.md)
的基础上，根据HFMA2的各个修饰符含义进行处理。

HADD2指令的求和结果可能产生NAN，这里着重指出对NAN的处理规则：
- 如果启用了.SAT修饰符，则输出中的NAN被转换为0
- 否则，参考[浮点数NAN处理规则](浮点数NAN处理规则.md)

  __Examples
```asm
HFMA2 R0, R1, R2.H1_H1, RZ; // {R0.H1,R0.H0} = {R1.H1,R1.H0} * {R2.H1,R2.H1} + (+0.0)
```

  __Simulation
      vd = HFMA2(va, vb);

__DefOpcode HFMA2_RRR : [HFMA2]
  __Encoding
    field< 8,  4> SType stype == RRR;

    field<32,  8> Reg rb;
    field<64,  8> Reg rc;

    field<96,  1> SignModi rb.neg = False;
    field<97,  1> SignModi rb.abs = False;
    field<82,  2> HSel2 rb.hsel2 = H1_H0;

    field<74,  1> SignModi rc.neg = False;
    field<75,  1> SignModi rc.abs = False;
    field<84,  2> HSel2 rc.hsel2 = H1_H0;
  __OperandInfo
    InList<pg, ra, rb, rc>;
    OutList<rd>;
    Order<pg, rd, ra, rb, rc>;
    Bitwidth<rd> = 32;
    Bitwidth<ra> = 32;
    Bitwidth<rb> = 32;
    Bitwidth<rc> = 32;
  __Exception

__DefOpcode HFMA2_RRI : [HFMA2]
  __Encoding
    field< 8,  4> SType stype == RRI;

    field<32, 32> F16ImmX2 vc;
    field<64,  8> Reg rb;

    field<74,  1> SignModi rb.neg = False;
    field<75,  1> SignModi rb.abs = False;
    field<82,  2> HSel2 rb.hsel2 = H1_H0;
  __OperandInfo
    InList<pg, ra, rb, vc>;
    OutList<rd>;
    Order<pg, rd, ra, rb, vc>;
    Bitwidth<rd> = 32;
    Bitwidth<ra> = 32;
    Bitwidth<rb> = 32;
    Bitwidth<vc> = 32;
    AsmFormat<vc> = CvtFImm(vc, hfmt_v2);

__DefOpcode HFMA2_RIR : [HFMA2]
  __Encoding
    field< 8,  4> SType stype == RIR;

    field<32, 32> F16ImmX2 vb;
    field<64,  8> Reg rc;

    field<74,  1> SignModi rc.neg = False;
    field<75,  1> SignModi rc.abs = False;
    field<84,  2> HSel2 rc.hsel2 = H1_H0;
  __OperandInfo
    InList<pg, ra, vb, rc>;
    OutList<rd>;
    Order<pg, rd, ra, vb, rc>;
    Bitwidth<rd> = 32;
    Bitwidth<ra> = 32;
    Bitwidth<vb> = 32;
    Bitwidth<rc> = 32;
    AsmFormat<vb> = CvtFImm(vb, hfmt_v2);

__DefOpcode HFMA2_RRU : [HFMA2]
  __Encoding
    field< 8,  4> SType stype == RRU;
    field<32,  6> UReg urc;
    field<64,  8> Reg rb;

    field<96,  1> SignModi urc.neg = False;
    field<97,  1> SignModi urc.abs = False;
    field<84,  2> HSel2 urc.hsel2 = H1_H0;

    field<74,  1> SignModi rb.neg = False;
    field<75,  1> SignModi rb.abs = False;
    field<82,  2> HSel2 rb.hsel2 = H1_H0;
  __OperandInfo
    InList<pg, ra, rb, urc>;
    OutList<rd>;
    Order<pg, rd, ra, rb, urc>;
    Bitwidth<rd> = 32;
    Bitwidth<ra> = 32;
    Bitwidth<rb> = 32;
    Bitwidth<urc> = 32;

__DefOpcode HFMA2_RUR : [HFMA2]
  __Encoding
    field< 8,  4> SType stype == RUR;

    field<32,  6> UReg urb;
    field<64,  8> Reg rc;

    field<96,  1> SignModi urb.neg = False;
    field<97,  1> SignModi urb.abs = False;
    field<82,  2> HSel2 urb.hsel2 = H1_H0;

    field<74,  1> SignModi rc.neg = False;
    field<75,  1> SignModi rc.abs = False;
    field<84,  2> HSel2 rc.hsel2 = H1_H0;
  __OperandInfo
    InList<pg, ra, urb, rc>;
    OutList<rd>;
    Order<pg, rd, ra, urb, rc>;
    Bitwidth<rd> = 32;
    Bitwidth<ra> = 32;
    Bitwidth<urb> = 32;
    Bitwidth<rc> = 32;

__DefOpcode HFMA2_RRC : [HFMA2]
  __Encoding
    field< 8,  4> SType stype == RRC;
    field<32, 22> CMem vc;

    field<64,  8> Reg rb;

    field<96,  1> SignModi vc.neg = False;
    field<97,  1> SignModi vc.abs = False;
    field<84,  2> HSel2 vc.hsel2 = H1_H0;

    field<74,  1> SignModi rb.neg = False;
    field<75,  1> SignModi rb.abs = False;
    field<82,  2> HSel2 rb.hsel2 = H1_H0;
  __OperandInfo
    InList<pg, ra, rb, vc>;
    OutList<rd>;
    Order<pg, rd, ra, rb, vc>;
    Bitwidth<rd> = 32;
    Bitwidth<ra> = 32;
    Bitwidth<rb> = 32;
    Bitwidth<vc> = 32;

__DefOpcode HFMA2_RCR : [HFMA2]
  __Encoding
    field< 8,  4> SType stype == RCR;

    field<32, 22> CMem vb;

    field<64,  8> Reg rc;

    field<96,  1> SignModi vb.neg = False;
    field<97,  1> SignModi vb.abs = False;

    field<74,  1> SignModi rc.neg = False;
    field<75,  1> SignModi rc.abs = False;

    field<82,  2> HSel2 vb.hsel2 = H1_H0;
    field<84,  2> HSel2 rc.hsel2 = H1_H0;
  __OperandInfo
    InList<pg, ra, vb, rc>;
    OutList<rd>;
    Order<pg, rd, ra, vb, rc>;
    Bitwidth<rd> = 32;
    Bitwidth<ra> = 32;
    Bitwidth<vb> = 32;
    Bitwidth<rc> = 32;

__DefOptype HMNMX2 : [HALU]
  __Encoding
    field< 0,  8> Optype optype == HMNMX2;

    field<98, 3> Pred pp;
    field<101, 1> PModi pp.not=False;

    field<16,  8> Reg rd;
    field<24,  8> Reg ra;
    field<80,  2> HSel2 ra.hsel2 = H1_H0;

    field<72,  1> SignModi ra.neg = False;
    field<73,  1> SignModi ra.abs = False;

    field<76,  1> FPFtz ftz = NoFTZ;
    field<84,  1> NAN nan = NoNAN;

    field<94,  1> HFmtV2 hfmt_v2 = F16_V2;

  __Syntax
```asm
HMNMX2{.hfmt_v2}{.FTZ}{.NAN} Rd, {-}{|}Ra{.hsel2}{|}, {-}{|}SrcB{.hsel2}{|}, {!}pp      $sched $req ;

.hfmt_v2 = {.F16_V2*, .BF16_V2}
.hsel2 = {.H1_H0*, .H0_H0, .H1_H1}
```

  __Description
双路选择输入16bit浮点数的最大/最小值输出，即Rd = minmax(Ra, SrcB, pp)。

输入谓词pp同时决定了双路选择最大还是最小值输出。

输入输出均为32bit，表示两路选择所涉及的操作数。
其中第1路选择结果写入Rd的低16bit，第2路选择结果写入Rd的高16bit。

  __OperandInfo
Rd和Ra必须来源于GPR。

SrcB可以来源于GPR、UR、F16ImmX2或cmem。

Ra和SrcB可以添加一个负号（-）前缀，表示取来源的相反数作为操作数。

F16ImmX2类型浮点向量立即数的使用规范请参考[浮点数向量立即数](操作数汇编显示规则.md#浮点数向量立即数)。

对于非立即数的输入，可以选择添加负号、绝对值和.hsel2修饰符。
.hsel2修饰符的含义见下面__ModifierInfo的说明。

同时存在多种修饰符时，按照：先取绝对值，再取相反数的优先级次序结合。

pp必须来源于PR，且可以添加一个逻辑非（!）前缀，表示取反作为操作数。

  __ModifierInfo
.hfmt_v2表示输入/输出操作数的类型，可取值包括.F16_V2（默认值，可省略）和.BF16_V2。

操作数修饰符.hsel2可取值为.H1_H0（默认，可省略）、.H0_H0或.H1_H1。

| .hsel2 | 含义 |
|:--:|:---|
|.H1_H0| 选取32bit输入的低16bit作为第1路输入，高16bit作为第2路输入|
|.H0_H0| 选取32bit输入的低16bit复制2份，同时作为2路的输入 |
|.H1_H1| 选取32bit输入的高16bit复制2份，同时作为2路的输入 |

如果输入为F16ImmX2立即数，则直接以立即数的低16bit和高16bit分别作为第1路和第2路输入。

可选修饰符.FTZ表示如果输入中出现了非规格化浮点数（subnormal number），则将其转换为有符号0（即保持符号位不变，其他bit全部置0）再参与选择。

可选修饰符.NAN表示如果某一路输入Ra和SrcB中有至少1个NAN，该路输出固定为16bit浮点数的自定义NAN（0x7FFF）。

如果不启用.NAN修饰符时，对于某一路输入含NAN的情况，该路的输出为：
- 如果Ra和SrcB中有且仅有1个NAN，输出为非NAN的那个数
- 如果Ra和SrcB都是NAN，输出为0x7FFF

  __Semantics
16bit浮点数最大最小值选择的语义基本与32bit浮点数一致，请参考
[[FMNMX]]指令的Semantics部分。

  __Examples
```asm
HMNMX2 R0, -|R1|,    -|R2|, !PT ;
HMNMX2 R0,    R1,     1,-4,  P0 ;
HMNMX2 R0,    R1, 0.125,-2, !P1 ;
```

__DefOpcode HMNMX2_RR : [HMNMX2]
  __Encoding
    field< 8,  4> SType stype == RR;
    field<32,  8> Reg rb;
    field<96,  1> SignModi rb.neg = False;
    field<97,  1> SignModi rb.abs = False;
    field<82, 2> HSel2 rb.hsel2 = H1_H0;
  __OperandInfo
    InList<pg, ra, rb, pp>;
    OutList<rd>;
    Order<pg, rd, ra, rb, pp>;
    Bitwidth<rd> = 32;
    Bitwidth<ra> = 32;
    Bitwidth<rb> = 32;
  __Exception

__DefOpcode HMNMX2_RU : [HMNMX2]
  __Encoding
    field< 8,  4> SType stype == RU;

    field<32,  6> UReg urb;

    field<96,  1> SignModi urb.neg = False;
    field<97,  1> SignModi urb.abs = False;
    field<82, 2> HSel2 urb.hsel2 = H1_H0;
  __OperandInfo
    InList<pg, ra, urb, pp>;
    OutList<rd>;
    Order<pg, rd, ra, urb, pp>;
    Bitwidth<rd> = 32;
    Bitwidth<ra> = 32;
    Bitwidth<urb> = 32;

__DefOpcode HMNMX2_RI : [HMNMX2]
  __Encoding
    field< 8,  4> SType stype == RI;
    field<32, 32> F16ImmX2 vb;
  __OperandInfo
    InList<pg, ra, vb, pp>;
    OutList<rd>;
    Order<pg, rd, ra, vb, pp>;
    Bitwidth<rd> = 32;
    Bitwidth<ra> = 32;
    Bitwidth<vb> = 32;
    AsmFormat<vb> = CvtFImm(vb, hfmt_v2);

__DefOpcode HMNMX2_RC : [HMNMX2]
  __Encoding
    field< 8,  4> SType stype == RC;
    field<32, 22> CMem vb;
    field<96,  1> SignModi vb.neg = False;
    field<97,  1> SignModi vb.abs = False;
    field<82,  2> HSel2 vb.hsel2 = H1_H0;
  __OperandInfo
    InList<pg, ra, vb, pp>;
    OutList<rd>;
    Order<pg, rd, ra, vb, pp>;
    Bitwidth<rd> = 32;
    Bitwidth<ra> = 32;
    Bitwidth<vb> = 32;

__DefOptype HSETP2 : [HALU]
  __Encoding
    field<0,   8> Optype optype == HSETP2;
    field<98, 3> Pred pp = PT;
    field<101, 1> PModi pp.not=False;
    field<106, 3> Pred pu;
    field<109, 3> Pred pv;

    field<76,  1> FPFtz ftz = NoFTZ;

    field<24,  8> Reg ra;
    field<72,  1> SignModi ra.neg = False;
    field<73,  1> SignModi ra.abs = False;
    field<80,  2> HSel2 ra.hsel2 = H1_H0;

    field<84,  2> LOPOp lop;
    field<86,  4> FCMPOp cmp;
    field<94,  1> HFmtV2 hfmt_v2 = F16_V2;

  __Syntax
```asm          
HSETP2{.hfmt_v2}{.FTZ}.cmp.lop pu, pv, {-}{|}Ra{.hsel2}{|}, {-}{|}SrcB{.hsel2}{|}{, {!}pp}      $sched $req ;

.hfmt_v2 = {.F16_V2*, .BF16_V2}
.cmp = {.EQ, .NE, .LT, .LE, .GT, .GE, .EQU, .NEU, .LTU, .LEU, .GTU, .GEU, .NAN, .NUM}
.lop = {.AND, .OR, .XOR}
.hsel2 = {.H1_H0*, .H0_H0, .H1_H1}
```

  __Description
分两路对2个输入浮点数进行指定的算术比较，将比较结果（布尔值）与一个额外的输入谓词进行指定的布尔运算，得到输出。
即{pu, pv} = (Ra cmp SrcB) lop pp;

Ra、SrcB均为32bit，用于表示两路比较所涉及的操作数。
其中第1路结果写入pu，第2路结果写入pv。

  __OperandInfo
Ra只能来源于GPR。

SrcB可以是GPR、UR、F16ImmX2或cmem。

F16ImmX2类型浮点向量立即数的使用规范请参考[浮点数向量立即数](操作数汇编显示规则.md#浮点数向量立即数)。

对于非立即数的输入，可以选择添加负号、绝对值和.hsel2修饰符。
.hsel2修饰符的含义见下面__ModifierInfo的说明。

同时存在多种修饰符时，按照：先取绝对值，再取相反数的优先级次序结合。

输出操作数pu、pv，输入操作数pp均为谓词，来源只能是PR。

输入操作数pp的默认值是PT（可以省略），且可添加一个逻辑非(!)前缀，表示取反作为操作数。

  __ModifierInfo
.hfmt_v2表示输入操作数的类型，可取值包括.F16_V2（默认值，可省略）和.BF16_V2。

.cmp决定对Ra、SrcB所作的算术比较，包含14种可取值。按照对输入NAN时的处理方式，.cmp的前12种可取值被分为ordered比较和unordered比较两类：

| ordered比较 | unordered比较 | 输入不含NAN时的语义 |
|:--:|:--:|:--:|
| .EQ | .EQU | == |
| .NE | .NEU | != |
| .LT | .LTU | <  |
| .LE | .LEU | <= |
| .GT | .GTU | >  |
| .GE | .GEU | >= |

二者的区别在于，当比较的两个操作数中至少含有1个NAN时：
- ordered比较：返回false
- unordered比较：返回true

.cmp的最后2种可取值.NAN和.NUM的含义如下：
- .NAN：参与比较的2个输入至少一个是NAN时，结果为true，否则为false
- .NUM：参与比较的2个输入都不是NAN时，结果为true，否则为false

.lop决定了将Ra、SrcB的比较结果与输入布尔值（操作数pp）进行何种布尔运算：

| .lop | 功能 |
|:--:|:--:|
| .AND | && |
| .OR  | \|\| |
| .XOR | ^ |

操作数修饰符.hsel2可取值为.H1_H0（默认，可省略）、.H0_H0或.H1_H1。

| .hsel2 | 含义 |
|:--:|:---|
|.H1_H0| 选取32bit输入的低16bit作为第1路输入，高16bit作为第2路输入|
|.H0_H0| 选取32bit输入的低16bit复制2份，同时作为2路的输入 |
|.H1_H1| 选取32bit输入的高16bit复制2份，同时作为2路的输入 |

如果输入为F16ImmX2立即数，则直接以立即数的低16bit和高16bit分别作为第1路和第2路输入。

可选修饰符.FTZ表示如果输入中有非规格化浮点数（subnormal number），则将其转换为有符号0（即保持符号位不变，其他bit全部置0）。

  __Semantics
```asm
HSETP2.hfmt_v2.ftz.cmp.lop pu, pv, Ra.hsel2, SrcB.hsel2, pp:
    // 分2路计算，但硬件上2路是同时进行的
    for (i = 0; i < 2; i++) {
        // 根据.hsel2，选取第i路的输入
        a = chooseInput(Ra  , i, Ra.hsel2);
        b = chooseInput(SrcB, i, SrcB.hsel2);
        // 处理输入中的非规格化浮点数
        if (.ftz == .FTZ) {
            if (isSubnormal(a) == true) {
                a = signZero(a);
            }
            if (isSubnormal(b) == true) {
                b = signZero(b);
            }
        }
        // 比较a与b
        t = a cmp b ? true : false;
        // 根据lop对t与pp进行布尔运算
        if (i == 0) {
            pu = t lop pp;
        } else {
            pv = t lop pp;
        }
    }
```

  __Examples
```asm
HSETP2.LE.AND     P0, P1,    R4,     R6,  PT;
HSETP2.FTZ.GTU.OR P0, P1, -|R5|,  -1, 0, !PT;
```

__DefOpcode HSETP2_RR : [HSETP2]
  __Encoding
    field< 8,  4> SType stype == RR;
    field<32,  8> Reg rb;
    field<96,  1> SignModi rb.neg = False;
    field<97,  1> SignModi rb.abs = False;
    field<82,  2> HSel2 rb.hsel2 = H1_H0;
  __OperandInfo
    InList<pg, ra, rb, pp>;
    OutList<pu, pv>;
    Order<pg, pu, pv, ra, rb, pp>;
    Bitwidth<ra> = 32;
    Bitwidth<rb> = 32;

__DefOpcode HSETP2_RU : [HSETP2]
  __Encoding
    field< 8,  4> SType stype == RU;
    field<32,  6> UReg urb;
    field<96,  1> SignModi urb.neg = False;
    field<97,  1> SignModi urb.abs = False;
    field<82,  2> HSel2 urb.hsel2 = H1_H0;
  __OperandInfo
    InList<pg, ra, urb, pp>;
    OutList<pu, pv>;
    Order<pg, pu, pv, ra, urb, pp>;
    Bitwidth<ra> = 32;
    Bitwidth<urb> = 32;

__DefOpcode HSETP2_RI : [HSETP2]
  __Encoding
    field< 8,  4> SType stype == RI;
    field<32, 32> F16ImmX2 vb;
  __OperandInfo
    InList<pg, ra, vb, pp>;
    OutList<pu, pv>;
    Order<pg, pu, pv, ra, vb, pp>;
    Bitwidth<ra> = 32;
    Bitwidth<vb> = 32;
    AsmFormat<vb> = CvtFImm(vb, hfmt_v2);

__DefOpcode HSETP2_RC : [HSETP2]
  __Encoding
    field< 8,  4> SType stype == RC;
    field<32, 22> CMem vb;
    field<96,  1> SignModi vb.neg = False;
    field<97,  1> SignModi vb.abs = False;
    field<82,  2> HSel2 vb.hsel2 = H1_H0;
  __OperandInfo
    InList<pg, ra, vb, pp>;
    OutList<pu, pv>;
    Order<pg, pu, pv, ra, vb, pp>;
    Bitwidth<ra> = 32;
    Bitwidth<vb> = 32;

__DefOptype HSET2 : [HALU]
  __Encoding
    field< 0,  8> Optype optype == HSET2;
    field<98, 3> Pred pp = PT;
    field<101, 1> PModi pp.not = False;
    field<76,  1> FPFtz ftz = NoFTZ;
    field<16,  8> Reg rd;
    field<24,  8> Reg ra;
    field<72,  1> SignModi ra.neg = False;
    field<73,  1> SignModi ra.abs = False;
    field<80,  2> HSel2 ra.hsel2 = H1_H0;

    field<84,  2> LOPOp lop;
    field<86,  4> FCMPOp cmp;
    field<90,  1> BVal bval = BM;
    field<94,  1> HFmtV2 hfmt_v2 = F16_V2;

  __Syntax
```asm          
HSET2{.hfmt_v2}{.FTZ}.cmp.lop{.bval} Rd, {-}{|}Ra{.hsel2}{|}, {-}{|}SrcB{.hsel2}{|}{, {!}pp}      $sched $req ;

.hfmt_v2 = {.F16_V2*, .BF16_V2}
.cmp = {.EQ, .NE, .LT, .LE, .GT, .GE, .EQU, .NEU, .LTU, .LEU, .GTU, .GEU, .NAN, .NUM}
.lop = {.AND, .OR, .XOR}
.bval = {.BM*, .BF}
.hsel2 = {.H1_H0*, .H0_H0, .H1_H1}
```
  __Description
分两路对2个输入浮点数进行指定的算术比较，将比较结果（布尔值）与一个额外的输入谓词进行指定的布尔运算，得到输出。
即Rd = (Ra CmpOp SrcB) BoolOp pp;

Rd、Ra、SrcB均为32bit，用于表示两路比较所涉及的操作数。
其中第1路结果写入Rd的低16bit，第2路结果写入Rd的高16bit。

  __OperandInfo
Rd和Ra只能来源于GPR。

SrcB可以是GPR、UR、F16ImmX2或cmem。

F16ImmX2类型浮点向量立即数的使用规范请参考[浮点数向量立即数](操作数汇编显示规则.md#浮点数向量立即数)。

对于非立即数的输入，可以选择添加负号、绝对值和.hsel2修饰符。
.hsel2修饰符的含义见下面__ModifierInfo的说明。

同时存在多种修饰符时，按照：先取绝对值，再取相反数的优先级次序结合。

输入操作数pp的默认值是PT（可以省略），且可添加一个逻辑非(!)前缀，表示取反作为操作数。

  __ModifierInfo
.hfmt_v2表示输入操作数的类型，可取值包括.F16_V2（默认值，可省略）和.BF16_V2。

.cmp决定对Ra、SrcB所作的算术比较，包含14种可取值。按照对输入NAN时的处理方式，.cmp的前12种可取值被分为ordered比较和unordered比较两类：

| ordered比较 | unordered比较 | 输入不含NAN时的语义 |
|:--:|:--:|:--:|
| .EQ | .EQU | == |
| .NE | .NEU | != |
| .LT | .LTU | <  |
| .LE | .LEU | <= |
| .GT | .GTU | >  |
| .GE | .GEU | >= |

二者的区别在于，当比较的两个操作数中至少含有1个NAN时：
- ordered比较：返回false
- unordered比较：返回true

.cmp的最后2种可取值.NAN和.NUM的含义如下：
- .NAN：参与比较的2个输入至少一个是NAN时，结果为true，否则为false
- .NUM：参与比较的2个输入都不是NAN时，结果为true，否则为false

.lop决定了将Ra、SrcB的比较结果与输入布尔值（操作数pp）进行何种布尔运算：

| .lop | 功能 |
|:--:|:--:|
| .AND | && |
| .OR  | \|\| |
| .XOR | ^ |

操作数修饰符.hsel2可取值为.H1_H0（默认，可省略）、.H0_H0或.H1_H1。

| .hsel2 | 含义 |
|:--:|:---|
|.H1_H0| 选取32bit输入的低16bit作为第1路输入，高16bit作为第2路输入|
|.H0_H0| 选取32bit输入的低16bit复制2份，同时作为2路的输入 |
|.H1_H1| 选取32bit输入的高16bit复制2份，同时作为2路的输入 |

如果输入为F16ImmX2立即数，则直接以立即数的低16bit和高16bit分别作为第1路和第2路输入。

.bval可取值为.BM（默认，可省略）或.BF，用于决定单路的布尔运算结果如何转换为16bit：
- .BM：将true转换为0xFFFF，false转换为0x0000
- .BF：将true转换为.type类型16bit浮点数的1.0（F16为0x3C00，BF16为0x3F80），false转换为0x0000

可选修饰符.FTZ表示如果输入中有非规格化浮点数（subnormal number），则将其转换为有符号0（即保持符号位不变，其他bit全部置0）。

  __Semantics
```asm
HSET2.hfmt_v2.ftz.cmp.lop.bval Rd, Ra.hsel2, SrcB.hsel2, pp:
    // 分2路计算，但硬件上2路是同时进行的
    for (i = 0; i < 2; i++) {
        // 根据.hsel2，选取第i路的输入
        a = chooseInput(Ra  , i, Ra.hsel2);
        b = chooseInput(SrcB, i, SrcB.hsel2);
        // 处理输入中的非规格化浮点数
        if (.ftz == .FTZ) {
            if (isSubnormal(a) == true) {
                a = signZero(a);
            }
            if (isSubnormal(b) == true) {
                b = signZero(b);
            }
        }
        // 比较a与b
        t = a cmp b ? true : false;
        // 根据lop对t与pp进行布尔运算
        booleanResult = t lop pp;
        // 根据.bval转换为16bit单路输出
        if (booleanResult == false) {
            d = 0x0000;
        } else if (.bval == .BM) {
            d = 0xFFFF;
        } else {
            d = .hfmt_v2 == .F16_V2 ? 0x3C00 : 0x3F80;
        }
        // 输出单路结果到Rd的half word
        if (i == 0) {
            Rd[15:0] = d & 0xFFFF;
        } else {
            Rd[31:16] = d & 0xFFFF;
        }
    }
```

  __Examples
```asm
HSET2.LE.AND        R1,    R4,     R6,  PT;
HSET2.FTZ.GTU.OR.BF R0, -|R5|,  -1, 0, !PT;
```

__DefOpcode HSET2_RR : [HSET2]
  __Encoding
    field< 8,  4> SType stype == RR;
    field<32,  8> Reg rb;
    field<96,  1> SignModi rb.neg = False;
    field<97,  1> SignModi rb.abs = False;
    field<82,  2> HSel2 rb.hsel2 = H1_H0;
  __OperandInfo
    InList<pg, ra, rb, pp>;
    OutList<rd>;
    Order<pg, rd, ra, rb, pp>;
    Bitwidth<ra> = 32;
    Bitwidth<rb> = 32;
    Bitwidth<rd> = 32;

__DefOpcode HSET2_RU : [HSET2]
  __Encoding
    field< 8,  4> SType stype == RU;
    field<32,  6> UReg urb;
    field<96,  1> SignModi urb.neg = False;
    field<97,  1> SignModi urb.abs = False;
    field<82,  2> HSel2 urb.hsel2 = H1_H0;
  __OperandInfo
    InList<pg, ra, urb, pp>;
    OutList<rd>;
    Order<pg, rd, ra, urb, pp>;
    Bitwidth<ra> = 32;
    Bitwidth<urb> = 32;
    Bitwidth<rd> = 32;

__DefOpcode HSET2_RI : [HSET2]
  __Encoding
    field< 8,  4> SType stype == RI;
    field<32, 32> F16ImmX2 vb;
  __OperandInfo
    InList<pg, ra, vb, pp>;
    OutList<rd>;
    Order<pg, rd, ra, vb, pp>;
    Bitwidth<ra> = 32;
    Bitwidth<vb> = 32;
    Bitwidth<rd> = 32;
    AsmFormat<vb> = CvtFImm(vb, hfmt_v2);

__DefOpcode HSET2_RC : [HSET2]
  __Encoding
    field< 8,  4> SType stype == RC;
    field<32, 22> CMem vb;
    field<96,  1> SignModi vb.neg = False;
    field<97,  1> SignModi vb.abs = False;
    field<82,  2> HSel2 vb.hsel2 = H1_H0;
  __OperandInfo
    InList<pg, ra, vb, pp>;
    OutList<rd>;
    Order<pg, rd, ra, vb, pp>;
    Bitwidth<ra> = 32;
    Bitwidth<vb> = 32;
    Bitwidth<rd> = 32;